(function () {
    "use strict";

    require("./slice-args");
    require("./assign");

    module.exports = function defineType(init) {
        var args = Function.sliceArgs(arguments);
        if (!(init instanceof Function)) {
            args.unshift(function () {});
            return defineType.apply(this, args);
        }

        var mixins = args.slice(1);

        var ctors = mixins.filter(function (mixin) {
            return mixin.constructor instanceof Function;
        }).map(function (mixin) {
            return mixin.constructor;
        }).reverse();
        ctors.push(init);

        var Type = function () {
            var args = Function.sliceArgs(arguments);
            ctors.forEach(function (ctor) {
                ctor.apply(this, args);
            }, this);
        };

        if (mixins.length) {
            Type.prototype = Object.assign.apply(this, mixins);
            Object.defineProperty(Type.prototype, "constructor", {
                value: Type
            });
        }

        return Type;
    };
})();
